package com.blog.wl2023.service.admin;

import cn.hutool.core.util.StrUtil;
import com.blog.wl2023.entity.*;
import com.blog.wl2023.entity.response.PageResult;
import com.blog.wl2023.entity.response.Result;
import com.blog.wl2023.repository.*;
import jakarta.persistence.criteria.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author wule
 * @date 2023-11-02  20:00
 * @desc
 */
@Service
public class ManageService {

	@Autowired
	ArticleRepository articleRepository;
	@Autowired
	CapriceRepository capriceRepository;

	@Autowired
	TypeRepository typeRepository;

	@Autowired
	ArticleCommentRepository articleCommentRepository;

	@Autowired
	TreasureChestsRepository treasureChestsRepository;

	@Autowired
	MessageListRepository messageListRepository;

	@Autowired
	UserRepository userRepository;

	@Autowired
	AnnouncementRepository announcementRepository;

	public PageResult manageGetArticles(int pageNo,
	                                    int pageSize,
	                                    String title,
	                                    String typeId,
	                                    String isTop,
	                                    String isDelete,
	                                    String summary) {
		//查询条件存在这个对象中
		//重新Specification的toPredicate方法
		Specification<Article> specification = (root, criteriaQuery, criteriaBuilder) -> {
			// 创建一个存储所有约束的List
			List<Predicate> predicates = new ArrayList<>();
			//不为关于文章
			Path<String> uuid = root.get("uuid");
			Predicate uuidPredicate = criteriaBuilder.notEqual(uuid, "001");
			predicates.add(uuidPredicate);
			if (!StrUtil.hasEmpty(isDelete)) {
				//未删除
				Path<Integer> iD = root.get("isDelete");
				Predicate isDeletePredicate = criteriaBuilder.equal(iD, isDelete);
				predicates.add(isDeletePredicate);
			}
			if (!StrUtil.hasEmpty(isTop)) {
				//置顶
				Path<Integer> iT = root.get("isTop");
				Predicate isTopPredicate = criteriaBuilder.equal(iT, isTop);
				predicates.add(isTopPredicate);
			}
			if (!StrUtil.hasEmpty(title)) {
				Path<String> t = root.get("title");
				Predicate titlePredicate = criteriaBuilder.like(t, "%" + title + "%");
				predicates.add(titlePredicate);
			}
			if (!StrUtil.hasEmpty(summary)) {
				Path<String> s = root.get("summary");
				Predicate summaryPredicate = criteriaBuilder.like(s, "%" + summary + "%");
				predicates.add(summaryPredicate);
			}
			if (!StrUtil.hasEmpty(typeId)) {
				Path<String> tI = root.get("typeId");
				Predicate typeIdPredicate = criteriaBuilder.equal(tI, typeId);
				predicates.add(typeIdPredicate);
			}
			return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
		};

		//分页条件存在这个对象中
		PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createTime"));

		//进行查询操作，第一个参数是查询条件对象，第二个参数是分页对象
		//返回的数据都封装在了Page<Admin>对象中
		Page<Article> all = articleRepository.findAll(specification, pageRequest);

		return PageResult.ok(all.getContent(), all.getTotalElements(), all.getTotalPages());
	}

	public PageResult manageGetCaprices(int pageNo,
	                                    int pageSize,
	                                    String capriceContent,
	                                    String isDelete) {
		//查询条件存在这个对象中
		//重新Specification的toPredicate方法
		Specification<Caprice> specification = (root, criteriaQuery, criteriaBuilder) -> {
			// 创建一个存储所有约束的List
			List<Predicate> predicates = new ArrayList<>();
			if (!StrUtil.hasEmpty(isDelete)) {
				//未删除
				Path<Integer> iD = root.get("isDelete");
				Predicate isDeletePredicate = criteriaBuilder.equal(iD, isDelete);
				predicates.add(isDeletePredicate);
			}
			if (!StrUtil.hasEmpty(capriceContent)) {
				//置顶
				Path<String> cc = root.get("capriceContent");
				Predicate capriceContentPredicate = criteriaBuilder.like(cc, "%" + capriceContent + "%");
				predicates.add(capriceContentPredicate);
			}
			return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
		};

		//分页条件存在这个对象中
		PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createTime"));

		//进行查询操作，第一个参数是查询条件对象，第二个参数是分页对象
		//返回的数据都封装在了Page<Admin>对象中
		Page<Caprice> all = capriceRepository.findAll(specification, pageRequest);

		return PageResult.ok(all.getContent(), all.getTotalElements(), all.getTotalPages());
	}

	public PageResult manageGetTypes(int pageNo, int pageSize) {
		//分页条件存在这个对象中
		PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize);
		Page<Type> all = typeRepository.findAll(pageRequest);
		return PageResult.ok(all.getContent(), all.getTotalElements(), all.getTotalPages());
	}

	public PageResult manageGetCommentsByUuid(int pageNo, int pageSize, String articleId) {
		//查询条件存在这个对象中
		//重新Specification的toPredicate方法
		Specification<ArticleComment> specification = (root, criteriaQuery, criteriaBuilder) -> {
			//articleId相等
			Path<String> aId = root.get("articleId");
			Predicate articleIdPredicate = criteriaBuilder.equal(aId, articleId);
			Path<String> p = root.get("pId");
			Predicate pIdPredicate = criteriaBuilder.equal(p, "0");
			// 将用户表的字段值加入到查询结果中
			criteriaQuery.multiselect(
					root.get("uuid"),
					root.get("user").get("uuid"),
					root.get("commentContent"),
					root.get("createTime"),
					root.get("isDelete"),
					root.get("pId")
			);
			return criteriaBuilder.and(articleIdPredicate, pIdPredicate);
		};
		//分页条件存在这个对象中
		PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createTime"));

		//进行查询操作，第一个参数是查询条件对象，第二个参数是分页对象
		//返回的数据都封装在了Page<ArticleComment>对象中
		Page<ArticleComment> all = articleCommentRepository.findAll(specification, pageRequest);

		List<ArticleComment> content = all.getContent();
		if (content.size() > 0) {
			//进行子评论的查询
			List<ArticleComment> childComment = articleCommentRepository.findAdminArticleChildComment(articleId);
			if (childComment.size() > 0) {
				//设置评论数据的子节点
				for (ArticleComment pComment : content) {
					List<ArticleComment> comments = childComment.stream().filter(comment -> pComment.getUuid().equals(comment.getPId()))
							.peek(
									comment -> {
										User user = comment.getUser();
										comment.setImageUrl(user.getImageUrl());
										comment.setUsername(user.getUsername());
										comment.setUser(null);
									}).collect(Collectors.toList());
					pComment.setChildComment(comments);
					//设置父评论的username和imageUrl
					pComment.setUsername(pComment.getUser().getUsername());
					pComment.setImageUrl(pComment.getUser().getImageUrl());
					pComment.setUser(null);
				}
			}
		}
		return PageResult.ok(content, all.getTotalElements(), all.getTotalPages());
	}

	public PageResult manageAllTreasureChests(int pageNo, int pageSize, String urlName, String description, String typeId) {
		//查询条件存在这个对象中
		//重新Specification的toPredicate方法
		Specification<TreasureChests> specification = (root, criteriaQuery, criteriaBuilder) -> {
			// 创建一个存储所有约束的List
			List<Predicate> predicates = new ArrayList<>();
			//未删除(删除键不做保留使用,而是判断是否审核通过,后面要删除直接删除,而不是逻辑删除)
			Path<Integer> iD = root.get("isDelete");
			Predicate isDeletePredicate = criteriaBuilder.equal(iD, 0);
			predicates.add(isDeletePredicate);

			if (!StrUtil.hasEmpty(typeId)) {
				Path<Integer> tI = root.get("typeId");
				Predicate typeIdPredicate = criteriaBuilder.equal(tI, typeId);
				predicates.add(typeIdPredicate);
			}
			if (!StrUtil.hasEmpty(description)) {
				Path<String> d = root.get("description");
				Predicate descriptionPredicate = criteriaBuilder.like(d, "%" + description + "%");
				predicates.add(descriptionPredicate);
			}
			if (!StrUtil.hasEmpty(urlName)) {
				Path<String> u = root.get("urlName");
				Predicate urlNamePredicate = criteriaBuilder.like(u, "%" + urlName + "%");
				predicates.add(urlNamePredicate);
			}
			return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
		};

		//分页条件存在这个对象中
		PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createTime"));

		//进行查询操作，第一个参数是查询条件对象，第二个参数是分页对象
		//返回的数据都封装在了Page<Admin>对象中
		Page<TreasureChests> all = treasureChestsRepository.findAll(specification, pageRequest);

		return PageResult.ok(all.getContent(), all.getTotalElements(), all.getTotalPages());
	}

	public PageResult manageGetMessageLists(int pageNo, int pageSize, String messageContent, String isDelete, String starTime, String endTime) {

		//查询条件存在这个对象中
		//重新Specification的toPredicate方法
		Specification<MessageList> specification = (root, criteriaQuery, criteriaBuilder) -> {
			// 创建一个存储所有约束的List
			List<Predicate> predicates = new ArrayList<>();
			if (!StrUtil.hasEmpty(isDelete)) {
//				是否逻辑删除(是否显示)
				Path<Integer> iD = root.get("isDelete");
				Predicate isDeletePredicate = criteriaBuilder.equal(iD, isDelete);
				predicates.add(isDeletePredicate);
			}
			if (!StrUtil.hasEmpty(messageContent)) {
				//置顶
				Path<String> mC = root.get("messageContent");
				Predicate capriceContentPredicate = criteriaBuilder.like(mC, "%" + messageContent + "%");
				predicates.add(capriceContentPredicate);
			}
			;
			if (!StrUtil.hasEmpty(starTime) && !StrUtil.hasEmpty(endTime)) {
				Instant s = Instant.parse(starTime);
				Instant e = Instant.parse(endTime);
				Timestamp star = Timestamp.from(s);
				Timestamp end = Timestamp.from(e);
				// 将前端传递的日期数组转换成Date类型
				Path<Date> createTimePath = root.get("createTime");
				Predicate dateRangePredicate = criteriaBuilder.between(createTimePath, star, end);
				predicates.add(dateRangePredicate);
			}
			// 将用户表的字段值加入到查询结果中
			criteriaQuery.multiselect(
					root.get("uuid"),
					root.get("user").get("uuid"),
					root.get("messageContent"),
					root.get("createTime"),
					root.get("isDelete")
			);
			return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
		};

		//分页条件存在这个对象中
		PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createTime"));

		//进行查询操作，第一个参数是查询条件对象，第二个参数是分页对象
		//返回的数据都封装在了Page<Admin>对象中
		Page<MessageList> all = messageListRepository.findAll(specification, pageRequest);

		List<MessageList> content = all.getContent();
		List<MessageList> messageLists = content.stream().peek(c -> {
			if (c.getUser() != null) {
				c.setImageUrl(c.getUser().getImageUrl());
				c.setUser(null);
			}
		}).toList();
		return PageResult.ok(messageLists, all.getTotalElements(), all.getTotalPages());
	}

	public PageResult manageGetUsers(int pageNo, int pageSize, String username, String email, String status) {

		//查询条件存在这个对象中
		//重新Specification的toPredicate方法
		Specification<User> specification = (root, criteriaQuery, criteriaBuilder) -> {
			// 创建一个存储所有约束的List
			List<Predicate> predicates = new ArrayList<>();
			if (!StrUtil.hasEmpty(username)) {
				Path<String> un = root.get("username");
				Predicate usernamePredicate = criteriaBuilder.like(un, "%" + username + "%");
				predicates.add(usernamePredicate);
			}
			if (!StrUtil.hasEmpty(email)) {
				Path<String> e = root.get("email");
				Predicate emailPredicate = criteriaBuilder.equal(e, email);
				predicates.add(emailPredicate);
			}
			if (!StrUtil.hasEmpty(status)) {
				Path<String> s = root.get("status");
				Predicate statusPredicate = criteriaBuilder.equal(s, status);
				predicates.add(statusPredicate);
			}
			return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
		};

		//分页条件存在这个对象中
		PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createTime"));

		//进行查询操作，第一个参数是查询条件对象，第二个参数是分页对象
		//返回的数据都封装在了Page<Admin>对象中
		Page<User> all = userRepository.findAll(specification, pageRequest);
		List<User> content = all.getContent();

		List<User> users = content.stream().peek(u -> {
			if (u.getCode() != null && !u.getCode().equals("")) {
				u.setStatus("-1");
			}
			u.setPassword(null);
			u.setCode(null);
		}).toList();
		return PageResult.ok(users, all.getTotalElements(), all.getTotalPages());
	}

	public Result manageGetAnnouncement() {
		List<Announcement> all = announcementRepository.findAll();
		return Result.ok(all);
	}

	public Result manageGetTreasureChestsByIsDelete() {
		List<TreasureChests> all = treasureChestsRepository.manageGetTreasureChestsByIsDelete();
		return Result.ok(all);
	}
}
